﻿Imports WiremetModel.Entities.OEM
Imports System.Globalization
Imports WiremetModel.Entities
Imports System.ComponentModel
Imports InputValidation
Imports InputValidation.GeneralRules
Imports InputValidation.GeneralRules.NumericInputRules

Public Class WireCertificatePrintingDialog

    Private _unitOfWork As UnitOfWork
    Private _shipment As Wysylka
    Private _orderLine As PozycjaZlecenia
    Private _material As Material
    Private _wiresList As IDictionary(Of Tracking.Drut, Boolean)
    Private _previousForm As Form
    Private _packagingDict As IDictionary(Of Pakowanie, Integer)
    Private _wireCertificate As WireCertificate
    Private _inputValidator As InputValidator

    Private _chemicalCompositionSet As New HashSet(Of WireCertificateChemicalComposition)
    Private _mechanicalParametersSet As New HashSet(Of WireCertificateMechanicalParameters)
    Private _packagingSet As New HashSet(Of WireCertificatePackaging)

    Private _refreshWytop As Boolean = True

    Public Sub New(ByVal shipment As Wysylka, ByVal orderLine As PozycjaZlecenia, ByVal material As Material, ByVal wiresList As IDictionary(Of Tracking.Drut, Boolean), ByRef previousForm As Form, ByVal wireCertificate As WireCertificate, ByRef unitOfWork As UnitOfWork)
        InitializeComponent()
        '_unitOfWork = New UnitOfWork()
        _unitOfWork = unitOfWork
        _inputValidator = New InputValidator()

        _shipment = shipment
        _orderLine = orderLine
        _material = material
        _wiresList = wiresList
        _previousForm = previousForm
        _wireCertificate = wireCertificate


        RefreshViewData()
        RefreshWireCertificateInput(orderLine, material, wiresList)


        If Not wireCertificate Is Nothing Then
            cmb_Gatunek.Text = wireCertificate.GatunekName
            cmb_Wytop.Text = wireCertificate.WytopName
            txt_NormaWykonania.Text = wireCertificate.NormaWykonania
        End If

        _chemicalCompositionSet = New HashSet(Of WireCertificateChemicalComposition)(wireCertificate.ChemicalComposition)
        RefreshChemicalCompositionTable(_chemicalCompositionSet.OrderByDescending(Function(x) x.ElementAmount))


        _mechanicalParametersSet = New HashSet(Of WireCertificateMechanicalParameters)()
        For Each wire As Tracking.Drut In wiresList.Where(Function(x) x.Value).Select(Function(x) x.Key).OrderBy(Function(x) x.Id)
            _mechanicalParametersSet.Add(New WireCertificateMechanicalParameters With {
                                         .Endurance = CType(wire.Kontrola.First.ZwickWytrzymalosc, Decimal),
                                         .Percent = CType(wire.Kontrola.First.ZwickProcentWydluzenia, Decimal),
                                         .Strength = CType(wire.Kontrola.First.ZwickSila, Decimal),
                                         .WireCertificate = _wireCertificate,
                                         .WireId = wire.Id.ToString()
                                     })
        Next
        RefreshMechanicalParametersTable(_mechanicalParametersSet.OrderBy(Function(x) x.Id))

        _packagingDict = GetPackagingDictByCount(_wiresList.Select(Function(x) x.Key.Kontrola.First.Pakowanie))
        _packagingSet = New HashSet(Of WireCertificatePackaging)()
        For Each kp As KeyValuePair(Of Pakowanie, Integer) In _packagingDict
            _packagingSet.Add(
                New WireCertificatePackaging With {
                    .Count = kp.Value,
                    .Name = kp.Key.Nazwa,
                    .Weight = CType(kp.Key.Waga, Decimal),
                    .WireCertificate = _wireCertificate
                }
            )
        Next
        RefreshPackagingTable(_packagingSet.OrderBy(Function(x) x.Name))

        

        dtp_DataWydruku.MaxDate = Today
        dtp_DataZamowienia.MaxDate = Today
        ClearErrorLabels()
    End Sub

    ' original certificate
    Public Sub New(ByVal wireCertificate As WireCertificate, ByRef previousForm As Form, ByRef unitOfWork As UnitOfWork)
        InitializeComponent()
        _unitOfWork = New UnitOfWork()
        _inputValidator = New InputValidator()
        _unitOfWork = unitOfWork

        _shipment = wireCertificate.Shipment
        _orderLine = wireCertificate.OrderLine
        _material = wireCertificate.Material
        _previousForm = previousForm
        _wireCertificate = wireCertificate

        RefreshViewData()
        RefreshWireCertificateInput(wireCertificate)

        _chemicalCompositionSet = New HashSet(Of WireCertificateChemicalComposition)(wireCertificate.ChemicalComposition)
        RefreshChemicalCompositionTable(_chemicalCompositionSet.OrderByDescending(Function(x) x.ElementAmount))

        _mechanicalParametersSet = New HashSet(Of WireCertificateMechanicalParameters)(wireCertificate.MechanicalParameters)
        RefreshMechanicalParametersTable(wireCertificate.MechanicalParameters.OrderBy(Function(x) x.WireId))

        _packagingSet = New HashSet(Of WireCertificatePackaging)(_wireCertificate.Packaging)
        RefreshPackagingTable(_packagingSet.OrderBy(Function(x) x.Name))

        txt_NormaWykonania.Text = wireCertificate.NormaWykonania

        dtp_DataWydruku.MaxDate = Today
        dtp_DataZamowienia.MaxDate = Today
        ClearErrorLabels()
    End Sub

    Private Sub WireCertificatePrintingDialog_Load(sender As Object, e As EventArgs) Handles Me.Load
        dgv_ChemicalComposition.ClearSelection()
        dgv_MechanicalParameters.ClearSelection()
        dgv_Packaging.ClearSelection()
    End Sub

    Private Sub WireCertificatePrintingDialog_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
        '_unitOfWork.Dispose()
    End Sub

    Private Sub ClearErrorLabels()
        lbl_DiameterError.Text = String.Empty
        lbl_DiameterToleranceMinusError.Text = String.Empty
        lbl_DiameterTolerancePlusError.Text = String.Empty
        lbl_WeightError.Text = String.Empty
        lbl_QuantityError.Text = String.Empty
    End Sub

    Private Function GetPackagingDictByCount(ByVal packagingList As IEnumerable(Of Pakowanie)) As IDictionary(Of Pakowanie, Integer)
        Dim dict As New Dictionary(Of Pakowanie, Integer)
        For Each packaging As Pakowanie In packagingList
            If Not dict.ContainsKey(packaging) Then
                dict.Add(packaging, 0)
            End If
            dict(packaging) += 1
        Next
        Return dict
    End Function

    Private Sub RefreshViewData()

        Dim gatunekRepository As New Repository(Of Gatunek)(_unitOfWork)
        Dim gatunekList As IEnumerable(Of Gatunek) = gatunekRepository.GetAll()
        InitializeInputComboBox(cmb_Gatunek, gatunekList)

    End Sub



    Private Sub InitializeInputComboBox(ByRef inputComboBox As ComboBox, ByVal data As IEnumerable(Of Object))

        inputComboBox.DataSource = New BindingSource(data, Nothing)
        inputComboBox.AutoCompleteCustomSource.Clear()
        inputComboBox.AutoCompleteCustomSource.AddRange(data.Select(Function(x) x.ToString()).ToArray())
        inputComboBox.SelectedIndex = -1

    End Sub


    Private Sub RefreshWireCertificateInput(ByVal orderLine As PozycjaZlecenia, ByVal material As Material, ByVal wiresList As IDictionary(Of Tracking.Drut, Boolean))

        gb_DaneSwiadectwa.Text = orderLine.Zlecenie.Klient.NazwaSkrocona + " - " + orderLine.Zlecenie.Numer
        txt_NumerZamowieniaKlienta.Text = orderLine.Zlecenie.NumerZamowieniaKlienta
        dtp_DataZamowienia.Value = orderLine.Zlecenie.DataZamowienia
        cmb_JezykGatunku.SelectedItem = GetReportLanguage(orderLine.Zlecenie.Klient.Kraj)
        txt_NormaWykonania.Text = material.Gatunek.NormaWykonania
        txt_Wymiar.Text = orderLine.Wymiar.ToString()
        txt_TolDolna.Text = orderLine.TolDolna.ToString()
        txt_TolGorna.Text = orderLine.TolGorna.ToString()
        txt_Waga.Text = wiresList.Sum(Function(x) x.Key.Kontrola.First().Ilosc).ToString() '.ToString("F2")
        txt_IloscSztuk.Text = wiresList.Count.ToString()
        txt_NumerFaktury.Text = ""
        cmb_WersjaJezykowa.SelectedItem = GetReportLanguage(orderLine.Zlecenie.Klient.Kraj)

        'Select Case cmb_JezykGatunku.SelectedItem.ToString()
        '    Case "polski"
        '        cmb_Gatunek.Text = _material.Gatunek.Nazwa
        '    Case "angielski"
        '        cmb_Gatunek.Text = _material.Gatunek.NazwaAng
        '    Case "niemiecki"
        '        cmb_Gatunek.Text = _material.Gatunek.NazwaNiem
        'End Select
        'cmb_Gatunek.Text = _material.Gatunek.NazwaAng
        cmb_Gatunek.SelectedItem = material.Gatunek

        cmb_Wytop.Text = material.Wytop
    End Sub


    Private Sub RefreshWireCertificateInput(ByVal wireCertificate As WireCertificate)
        gb_DaneSwiadectwa.Text = wireCertificate.CustomerShortName + " - " + wireCertificate.OrderNumber

        txt_NumerZamowieniaKlienta.Text = wireCertificate.CustomerOrderNumber
        dtp_DataWydruku.Value = wireCertificate.PrintTime
        dtp_DataZamowienia.Value = wireCertificate.OrderDate
        cmb_JezykGatunku.SelectedItem = wireCertificate.GatunekLanguage
        txt_NormaWykonania.Text = wireCertificate.NormaWykonania
        txt_Wymiar.Text = wireCertificate.Diameter.ToString()
        txt_TolDolna.Text = wireCertificate.ToleranceLower.ToString()
        txt_TolGorna.Text = wireCertificate.ToleranceUpper.ToString()
        txt_Waga.Text = wireCertificate.Weight.ToString()
        txt_IloscSztuk.Text = wireCertificate.SpoolCount.ToString()
        txt_NumerFaktury.Text = wireCertificate.InvoiceNumber
        cmb_WersjaJezykowa.SelectedItem = wireCertificate.ReportLanguage
        cmb_Gatunek.Text = wireCertificate.GatunekName
        cmb_Wytop.Text = wireCertificate.WytopName
    End Sub

    Private Sub RefreshChemicalCompositionTable(ByVal chemicalCompositionList As IEnumerable(Of WireCertificateChemicalComposition))
        dgv_ChemicalComposition.Rows.Clear()
        Dim index As Integer = 1

        For Each chem As WireCertificateChemicalComposition In chemicalCompositionList
            Dim rowIndex As Integer = dgv_ChemicalComposition.Rows.Add(index, chem.ElementName, chem.ElementAmount)
            dgv_ChemicalComposition.Rows(rowIndex).Tag = chem
            index += 1
        Next
        dgv_ChemicalComposition.ClearSelection()
    End Sub

    Private Sub RefreshMechanicalParametersTable(ByVal mechanicalParametersList As IEnumerable(Of WireCertificateMechanicalParameters))
        dgv_MechanicalParameters.Rows.Clear()
        Dim index As Integer = 1

        For Each parameters As WireCertificateMechanicalParameters In mechanicalParametersList
            Dim rowIndex As Integer = dgv_MechanicalParameters.Rows.Add(index, parameters.WireId, parameters.Strength, parameters.Endurance, parameters.Percent)
            dgv_MechanicalParameters.Rows(rowIndex).Tag = parameters
            index += 1
        Next
        dgv_MechanicalParameters.ClearSelection()
    End Sub

    Private Sub RefreshPackagingTable(ByVal packaginngList As IEnumerable(Of WireCertificatePackaging))
        dgv_Packaging.Rows.Clear()
        For Each packaging As WireCertificatePackaging In packaginngList
            Dim rowIndex As Integer = dgv_Packaging.Rows.Add(packaging.Id, packaging.Name, packaging.Weight, packaging.Count)
            dgv_Packaging.Rows(rowIndex).Tag = packaging
        Next
        dgv_Packaging.ClearSelection()
    End Sub

    Private Sub cmb_Gatunek_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles cmb_Gatunek.SelectedIndexChanged

        If _refreshWytop Then
            Dim selectedGatunek As Gatunek = CType(cmb_Gatunek.SelectedItem, Gatunek)
            Dim selectedWytop As String = cmb_Wytop.Text
            If selectedGatunek IsNot Nothing Then
                InitializeInputComboBox(cmb_Wytop, selectedGatunek.Materialy)
                cmb_Wytop.DisplayMember = "Wytop"
                'cmb_Wytop.Text = _swiadectwo.Wytop
                cmb_Wytop.Text = selectedWytop
                txt_NormaWykonania.Text = selectedGatunek.NormaWykonania
            End If
        End If

    End Sub

    Private Sub cmb_JezykGatunku_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles cmb_JezykGatunku.SelectedIndexChanged
        _refreshWytop = False
        Dim selectedGatunek As Gatunek = CType(cmb_Gatunek.SelectedItem, Gatunek)
        If selectedGatunek Is Nothing Then
            Select Case cmb_JezykGatunku.SelectedItem.ToString()
                Case "polski"
                    cmb_Gatunek.DisplayMember = "Nazwa"
                Case "angielski"
                    cmb_Gatunek.DisplayMember = "NazwaAng"
                Case "niemiecki"
                    cmb_Gatunek.DisplayMember = "NazwaNiem"
            End Select
        Else
            Select Case cmb_JezykGatunku.SelectedItem.ToString()
                Case "polski"
                    cmb_Gatunek.DisplayMember = "Nazwa"
                    cmb_Gatunek.Text = selectedGatunek.Nazwa
                Case "angielski"
                    cmb_Gatunek.DisplayMember = "NazwaAng"
                    cmb_Gatunek.Text = selectedGatunek.NazwaAng
                Case "niemiecki"
                    cmb_Gatunek.DisplayMember = "NazwaNiem"
                    cmb_Gatunek.Text = selectedGatunek.NazwaNiem
            End Select
        End If
        _refreshWytop = True
    End Sub

    Private Function GetReportLanguage(ByVal country As String) As String
        Select Case country.ToLower()
            Case "polska"
                Return "polski"
            Case "anglia"
                Return "angielski"
            Case "niemcy"
                Return "niemiecki"
            Case Else
                Return "angielski"
        End Select
    End Function

    Private Sub cmb_Wytop_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles cmb_Wytop.SelectedIndexChanged

        Dim selectedMaterial As Material = CType(cmb_Wytop.SelectedItem, Material)
        If selectedMaterial IsNot Nothing Then
            _chemicalCompositionSet.Clear()
            Dim chemsList As IList(Of SkladChemiczny)
            Try
                chemsList = selectedMaterial.SkladChemiczny.OrderByDescending(Function(x) Decimal.Parse(x.Wartosc, CultureInfo.InvariantCulture)).ToList()
            Catch ex As Exception
                chemsList = selectedMaterial.SkladChemiczny
            End Try

            For Each chemicalComposition As SkladChemiczny In chemsList
                _chemicalCompositionSet.Add(
                    New WireCertificateChemicalComposition With {
                        .ElementAmount = chemicalComposition.Wartosc,
                        .ElementName = chemicalComposition.Sklad.Pierwiastek.Nazwa,
                        .WireCertificate = _wireCertificate
                    })
            Next
            RefreshChemicalCompositionTable(_chemicalCompositionSet.OrderByDescending(Function(x) x.ElementAmount))
        End If
    End Sub



#Region "Input validation"

    Private Sub tb_Diameter_Validating(ByVal sender As Object, ByVal e As CancelEventArgs) Handles txt_Wymiar.Validating
        Dim notNullableTextInputValidatingSpecification As New NotNullableTextInputValidatingSpecification()
        Dim numericInputValidatingSpecification As New NumericInputValidatingSpecification()
        Dim numericPositiveInputValidatingSpecification As New NumericPositiveInputValidatingSpecification()
        _inputValidator.ValidateTextBox(txt_Wymiar, e, lbl_DiameterError, notNullableTextInputValidatingSpecification.And(numericInputValidatingSpecification).And(numericPositiveInputValidatingSpecification))
    End Sub

    Private Sub tb_DiameterToleranceMinus_Validating(ByVal sender As Object, ByVal e As CancelEventArgs) Handles txt_TolDolna.Validating
        Dim numericInputValidatingSpecification As New NumericInputValidatingSpecification()
        _inputValidator.ValidateTextBox(txt_TolDolna, e, lbl_DiameterToleranceMinusError, numericInputValidatingSpecification)
    End Sub

    Private Sub tb_DiameterTolerancePlus_Validating(ByVal sender As Object, ByVal e As CancelEventArgs) Handles txt_TolGorna.Validating
        Dim numericInputValidatingSpecification As New NumericInputValidatingSpecification()
        _inputValidator.ValidateTextBox(txt_TolDolna, e, lbl_DiameterToleranceMinusError, numericInputValidatingSpecification)

        If Not e.Cancel Then
            If txt_TolDolna.Text.Trim() = String.Empty Then
                _inputValidator.ValidateTextBox(txt_TolGorna, e, lbl_DiameterTolerancePlusError, numericInputValidatingSpecification)
            Else
                Dim diameterTolerancePlusValidatingSpecification As New DiameterTolerancePlusValidatingSpecification(Decimal.Parse(txt_TolDolna.Text.Trim()))
                _inputValidator.ValidateTextBox(txt_TolGorna, e, lbl_DiameterTolerancePlusError, numericInputValidatingSpecification.And(diameterTolerancePlusValidatingSpecification))
            End If
        End If
    End Sub

    Private Sub txt_Waga_Validating(ByVal sender As Object, ByVal e As CancelEventArgs) Handles txt_Waga.Validating
        Dim notNullableTextInputValidatingSpecification As New NotNullableTextInputValidatingSpecification()
        Dim numericInputValidatingSpecification As New NumericInputValidatingSpecification()
        Dim numericPositiveInputValidatingSpecification As New NumericPositiveInputValidatingSpecification()
        _inputValidator.ValidateTextBox(txt_Waga, e, lbl_WeightError, notNullableTextInputValidatingSpecification.And(numericInputValidatingSpecification).And(numericPositiveInputValidatingSpecification))
    End Sub

    Private Sub tb_Quantity_Validating(ByVal sender As Object, ByVal e As CancelEventArgs) Handles txt_IloscSztuk.Validating
        Dim notNullableTextInputValidatingSpecification As New NotNullableTextInputValidatingSpecification()
        Dim integerInputValidatingSpecification As New IntegerInputValidatingSpecification()
        Dim numericPositiveInputValidatingSpecification As New NumericPositiveInputValidatingSpecification()
        _inputValidator.ValidateTextBox(txt_IloscSztuk, e, lbl_QuantityError, notNullableTextInputValidatingSpecification.And(integerInputValidatingSpecification).And(numericPositiveInputValidatingSpecification))
    End Sub


    Private Sub tb_Diameter_Validated(ByVal sender As Object, ByVal e As EventArgs) Handles txt_Wymiar.Validated
        lbl_DiameterError.Text = String.Empty
    End Sub

    Private Sub tb_DiameterToleranceMinus_Validated(ByVal sender As Object, ByVal e As EventArgs) Handles txt_TolDolna.Validated
        lbl_DiameterToleranceMinusError.Text = String.Empty
    End Sub

    Private Sub tb_DiameterTolerancePlus_Validated(ByVal sender As Object, ByVal e As EventArgs) Handles txt_TolGorna.Validated
        lbl_DiameterTolerancePlusError.Text = String.Empty
    End Sub

    Private Sub txt_Weight_Validated(ByVal sender As Object, ByVal e As EventArgs) Handles txt_Waga.Validated
        lbl_WeightError.Text = String.Empty
    End Sub

    Private Sub tb_Quantity_Validated(ByVal sender As Object, ByVal e As EventArgs) Handles txt_IloscSztuk.Validated
        lbl_QuantityError.Text = String.Empty
    End Sub


    'Private Function IsInputNotEmpty(ByRef cell As DataGridViewCell) As Boolean

    '    If cell.Value Is Nothing OrElse cell.Value.ToString().Trim() = String.Empty Then
    '        cell.ErrorText = "Proszę, wypełnij to pole."
    '        cell.OwningRow.ErrorText = "Proszę, wypełnij to pole."
    '        Return False
    '    Else
    '        cell.ErrorText = String.Empty
    '        Return True
    '    End If
    'End Function

    'Private Function IsInputNumeric(ByRef cell As DataGridViewCell) As Boolean
    '    Dim value As Decimal
    '    If Not Decimal.TryParse(cell.Value.ToString(), value) Then
    '        cell.ErrorText = "Proszę, podaj wartość liczbową."
    '        cell.OwningRow.ErrorText = "Proszę, podaj wartość liczbową."
    '        Return False
    '    Else
    '        cell.ErrorText = String.Empty
    '        Return True
    '    End If
    'End Function

    'Private Function IsInputNumericPositive(ByRef cell As DataGridViewCell) As Boolean
    '    Dim value As Decimal
    '    Decimal.TryParse(cell.Value.ToString(), value)
    '    If value <= 0 Then
    '        cell.ErrorText = "Proszę, podaj wartość liczbową dodatnią."
    '        cell.OwningRow.ErrorText = "Proszę, podaj wartość liczbową dodatnią."
    '        Return False
    '    Else
    '        cell.ErrorText = String.Empty
    '        Return True
    '    End If
    'End Function

    'Private Function IsInputNumericNotNegative(ByRef cell As DataGridViewCell) As Boolean
    '    Dim value As Decimal
    '    Decimal.TryParse(cell.Value.ToString(), value)
    '    If value <= 0 Then
    '        cell.ErrorText = "Proszę, podaj wartość liczbową nieujemną."
    '        cell.OwningRow.ErrorText = "Proszę, podaj wartość liczbową nieujemną."
    '        Return False
    '    Else
    '        cell.ErrorText = String.Empty
    '        Return True
    '    End If
    'End Function


    'Private Sub dgv_ChemicalComposition_RowValidating(ByVal sender As Object, ByVal data As DataGridViewCellCancelEventArgs) Handles dgv_ChemicalComposition.RowValidating

    '    Dim row As DataGridViewRow = dgv_ChemicalComposition.Rows(data.RowIndex)

    '    Dim elementNameCell As DataGridViewCell = row.Cells("ElementName")
    '    Dim elementAmountCell As DataGridViewCell = row.Cells("ElementAmount")


    '    If row.IsNewRow AndAlso elementNameCell.Value Is Nothing AndAlso elementAmountCell.Value Is Nothing Then
    '        data.Cancel = False
    '    Else
    '        data.Cancel = Not (
    '        IsInputNotEmpty(elementNameCell) AndAlso
    '        IsInputNotEmpty(elementAmountCell) AndAlso
    '        IsInputNumeric(elementAmountCell) AndAlso
    '        IsInputNumericPositive(elementAmountCell)
    '        )
    '    End If
    'End Sub

    'Private Sub dgv_MechanicalParameters_RowValidating(ByVal sender As Object, ByVal data As DataGridViewCellCancelEventArgs) Handles dgv_MechanicalParameters.RowValidating

    '    Dim row As DataGridViewRow = dgv_MechanicalParameters.Rows(data.RowIndex)

    '    Dim numerCell As DataGridViewCell = row.Cells("Numer")
    '    Dim silaCell As DataGridViewCell = row.Cells("Sila")
    '    Dim wytrzymaloscCell As DataGridViewCell = row.Cells("Wytrzymalosc")
    '    Dim procentCell As DataGridViewCell = row.Cells("Procent")

    '    If row.IsNewRow AndAlso
    '        numerCell.Value Is Nothing AndAlso
    '        silaCell.Value Is Nothing AndAlso
    '        wytrzymaloscCell.Value Is Nothing AndAlso
    '        procentCell.Value Is Nothing Then
    '        data.Cancel = False
    '    Else
    '        data.Cancel = Not (
    '        IsInputNotEmpty(numerCell) AndAlso
    '        IsInputNotEmpty(silaCell) AndAlso IsInputNumeric(silaCell) AndAlso IsInputNumericNotNegative(silaCell) AndAlso
    '        IsInputNotEmpty(wytrzymaloscCell) AndAlso IsInputNumeric(wytrzymaloscCell) AndAlso IsInputNumericNotNegative(wytrzymaloscCell) AndAlso
    '        IsInputNotEmpty(procentCell) AndAlso IsInputNumeric(procentCell) AndAlso IsInputNumericNotNegative(procentCell)
    '        )
    '    End If
    'End Sub

    'Private Sub dgv_Packaging_RowValidating(ByVal sender As Object, ByVal data As DataGridViewCellCancelEventArgs) Handles dgv_Packaging.RowValidating

    '    Dim row As DataGridViewRow = dgv_Packaging.Rows(data.RowIndex)

    '    Dim name As DataGridViewCell = row.Cells("PackagingName")
    '    Dim weight As DataGridViewCell = row.Cells("PackagingWeight")
    '    Dim price As DataGridViewCell = row.Cells("PackagingPrice")
    '    Dim count As DataGridViewCell = row.Cells("PackagingCount")

    '    If row.IsNewRow AndAlso
    '        name.Value Is Nothing AndAlso
    '        weight.Value Is Nothing AndAlso
    '        price.Value Is Nothing AndAlso
    '        count.Value Is Nothing Then
    '        data.Cancel = False
    '    Else
    '        data.Cancel = Not (
    '        IsInputNotEmpty(name) AndAlso
    '        IsInputNotEmpty(weight) AndAlso IsInputNumeric(weight) AndAlso IsInputNumericNotNegative(weight) AndAlso
    '        IsInputNotEmpty(price) AndAlso IsInputNumeric(price) AndAlso IsInputNumericNotNegative(price) AndAlso
    '        IsInputNotEmpty(count) AndAlso IsInputNumeric(count) AndAlso IsInputNumericNotNegative(count)
    '        )
    '    End If
    'End Sub

    



    'Private Sub dgv_ChemicalComposition_CellValidating(ByVal sender As Object, _
    '    ByVal e As DataGridViewCellValidatingEventArgs) Handles dgv_ChemicalComposition.CellValidating

    '    ' Validate the CompanyName entry by disallowing empty strings.
    '    If dgv_ChemicalComposition.Columns(e.ColumnIndex).Name = "ElementName" Then
    '        If String.IsNullOrEmpty(e.FormattedValue.ToString()) Then
    '            dgv_ChemicalComposition.Rows(e.RowIndex).ErrorText = _
    '                "Proszę, podaj nazwę pierwiastka."
    '            e.Cancel = True
    '        End If


    '    ElseIf dgv_ChemicalComposition.Columns(e.ColumnIndex).Name = "ElementAmount" Then
    '        Dim elementAmount As Decimal
    '        If String.IsNullOrEmpty(e.FormattedValue.ToString()) Then
    '            dgv_ChemicalComposition.Rows(e.RowIndex).ErrorText = _
    '                "Proszę, podaj nazwę pierwiastka."
    '            e.Cancel = True
    '        ElseIf Not Decimal.TryParse(e.FormattedValue.ToString(), elementAmount) Then
    '            dgv_ChemicalComposition.Rows(e.RowIndex).ErrorText = _
    '                "Proszę, podaj wartość liczbową."
    '            e.Cancel = True
    '        ElseIf elementAmount < 0 Then
    '            dgv_ChemicalComposition.Rows(e.RowIndex).ErrorText = _
    '                "Proszę, podaj wartość liczbową dodatnią."
    '            e.Cancel = True
    '        End If
    '    End If

    'End Sub

    'Private Sub dgv_CellEndEdit(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) _
    '    Handles dgv_ChemicalComposition.CellEndEdit, dgv_MechanicalParameters.CellEndEdit, dgv_Packaging.CellEndEdit

    '    ' Clear the row error in case the user presses ESC. 
    '    Dim dgv As DataGridView = CType(sender, DataGridView)
    '    dgv.Rows(e.RowIndex).ErrorText = String.Empty

    'End Sub



#End Region

#Region "Chemical Composition Actions"
    Private Sub EnsureChemicalCompositionIsSelected()
        If dgv_ChemicalComposition.SelectedRows.Count = 0 Then
            Throw New Exception("Proszę, wybierz skład chemiczny, aby kontynuować.")
        End If
    End Sub

    Private Sub ts_btn_AddChemicalComposition_Click(sender As System.Object, e As System.EventArgs) Handles ts_btn_AddChemicalComposition.Click
        Try
            Dim chemicalCompositionInputDialog As New WireCertificateChemicalCompositionInputDialog()
            If chemicalCompositionInputDialog.ShowDialog() = Windows.Forms.DialogResult.OK Then
                Dim newChemicalComposition As WireCertificateChemicalComposition = chemicalCompositionInputDialog.ChemicalComposition
                newChemicalComposition.WireCertificate = _wireCertificate
                _chemicalCompositionSet.Add(newChemicalComposition)
                RefreshChemicalCompositionTable(_chemicalCompositionSet.OrderByDescending(Function(x) x.ElementAmount))
            End If
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    Private Sub ts_btn_EditChemicalComposition_Click(sender As System.Object, e As System.EventArgs) Handles ts_btn_EditChemicalComposition.Click
        Try
            EnsureChemicalCompositionIsSelected()
            Dim selectedChemicalComposition As WireCertificateChemicalComposition = CType(dgv_ChemicalComposition.SelectedRows(0).Tag, WireCertificateChemicalComposition)
            Dim chemicalCompositionInputDialog As New WireCertificateChemicalCompositionInputDialog(selectedChemicalComposition)
            If chemicalCompositionInputDialog.ShowDialog() = Windows.Forms.DialogResult.OK Then
                _chemicalCompositionSet.Remove(selectedChemicalComposition)
                _chemicalCompositionSet.Add(chemicalCompositionInputDialog.ChemicalComposition)
                RefreshChemicalCompositionTable(_chemicalCompositionSet.OrderByDescending(Function(x) x.ElementAmount))
            End If
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    Private Sub ts_btn_RemoveChemicalComposition_Click(sender As System.Object, e As System.EventArgs) Handles ts_btn_RemoveChemicalComposition.Click
        Try
            EnsureChemicalCompositionIsSelected()
            Dim confirmationDialogResult As DialogResult = MessageBox.Show("Czy jesteś pewień?", "Uwaga!", MessageBoxButtons.YesNo, MessageBoxIcon.Warning)
            If confirmationDialogResult <> Windows.Forms.DialogResult.Yes Then
                Return
            End If
            For Each selectedChemicalCompositionRow As DataGridViewRow In dgv_ChemicalComposition.SelectedRows
                Dim selectedChemicalComposition As WireCertificateChemicalComposition = CType(selectedChemicalCompositionRow.Tag, WireCertificateChemicalComposition)
                _chemicalCompositionSet.Remove(selectedChemicalComposition)
            Next
            RefreshChemicalCompositionTable(_chemicalCompositionSet.OrderByDescending(Function(x) x.ElementAmount))
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub
#End Region

#Region "Mechanical Parameters Actions"

    Private Sub EnsureMechanicalParameterIsSelected()
        If dgv_MechanicalParameters.SelectedRows.Count = 0 Then
            Throw New Exception("Proszę, wybierz szpulę, aby kontynuować.")
        End If
    End Sub

    Private Sub ts_btn_AddMechanicalParameter_Click(sender As System.Object, e As System.EventArgs) Handles ts_btn_AddMechanicalParameter.Click
        Try
            Dim mechanicalParametersInputDialog As New WireCertificateMechanicalParametersInputDialog()
            If mechanicalParametersInputDialog.ShowDialog() = Windows.Forms.DialogResult.OK Then
                Dim newMechanicalParameters As WireCertificateMechanicalParameters = mechanicalParametersInputDialog.MechanicalParameters
                newMechanicalParameters.WireCertificate = _wireCertificate
                _mechanicalParametersSet.Add(newMechanicalParameters)
                RefreshMechanicalParametersTable(_mechanicalParametersSet.OrderBy(Function(x) x.WireId))
            End If
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    Private Sub ts_EditMechanicalParameter_Click(sender As System.Object, e As System.EventArgs) Handles ts_EditMechanicalParameter.Click
        Try
            EnsureMechanicalParameterIsSelected()
            Dim selectedMechanicalParameter As WireCertificateMechanicalParameters = CType(dgv_MechanicalParameters.SelectedRows(0).Tag, WireCertificateMechanicalParameters)
            Dim mechanicalParametersInputDialog As New WireCertificateMechanicalParametersInputDialog(selectedMechanicalParameter)
            If mechanicalParametersInputDialog.ShowDialog() = Windows.Forms.DialogResult.OK Then
                _mechanicalParametersSet.Remove(selectedMechanicalParameter)
                _mechanicalParametersSet.Add(mechanicalParametersInputDialog.MechanicalParameters)
                RefreshMechanicalParametersTable(_mechanicalParametersSet.OrderBy(Function(x) x.WireId))
            End If
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    Private Sub ts_btn_RemoveMechanicalParameter_Click(sender As System.Object, e As System.EventArgs) Handles ts_btn_RemoveMechanicalParameter.Click
        Try
            EnsureMechanicalParameterIsSelected()
            Dim confirmationDialogResult As DialogResult = MessageBox.Show("Czy jesteś pewień?", "Uwaga!", MessageBoxButtons.YesNo, MessageBoxIcon.Warning)
            If confirmationDialogResult <> Windows.Forms.DialogResult.Yes Then
                Return
            End If

            For Each selectedMechanicalParameterRow As DataGridViewRow In dgv_MechanicalParameters.SelectedRows
                Dim selectedMechanicalParameter As WireCertificateMechanicalParameters = CType(selectedMechanicalParameterRow.Tag, WireCertificateMechanicalParameters)
                _mechanicalParametersSet.Remove(selectedMechanicalParameter)
            Next
            RefreshMechanicalParametersTable(_mechanicalParametersSet.OrderBy(Function(x) x.WireId))
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub
#End Region

#Region "Packaging Actions"
    Private Sub EnsurePackagingIsSelected()
        If dgv_Packaging.SelectedRows.Count = 0 Then
            Throw New Exception("Proszę, wybierz opakowanie, aby kontynuować.")
        End If
    End Sub

    Private Sub ts_btn_AddPackaging_Click(sender As System.Object, e As System.EventArgs) Handles ts_btn_AddPackaging.Click
        Try
            Dim packagingInputDialog As New WireCertificatePackagingInputDialog()
            If packagingInputDialog.ShowDialog() = Windows.Forms.DialogResult.OK Then
                Dim newPackaging As WireCertificatePackaging = packagingInputDialog.Packaging
                newPackaging.WireCertificate = _wireCertificate
                _packagingSet.Add(newPackaging)
                RefreshPackagingTable(_packagingSet.OrderBy(Function(x) x.Name))
            End If
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    Private Sub ts_btn_EditPackaging_Click(sender As System.Object, e As System.EventArgs) Handles ts_btn_EditPackaging.Click
        Try
            EnsurePackagingIsSelected()
            Dim selectedPackaging As WireCertificatePackaging = CType(dgv_Packaging.SelectedRows(0).Tag, WireCertificatePackaging)
            Dim packagingInputDialog As New WireCertificatePackagingInputDialog(selectedPackaging)
            If packagingInputDialog.ShowDialog() = Windows.Forms.DialogResult.OK Then
                _packagingSet.Remove(selectedPackaging)
                _packagingSet.Add(packagingInputDialog.Packaging)
                RefreshPackagingTable(_packagingSet.OrderBy(Function(x) x.Name))
            End If
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    Private Sub ts_btn_RemovePackaging_Click(sender As System.Object, e As System.EventArgs) Handles ts_btn_RemovePackaging.Click
        Try
            EnsurePackagingIsSelected()
            Dim confirmationDialogResult As DialogResult = MessageBox.Show("Czy jesteś pewień?", "Uwaga!", MessageBoxButtons.YesNo, MessageBoxIcon.Warning)
            If confirmationDialogResult <> Windows.Forms.DialogResult.Yes Then
                Return
            End If
            For Each selectedPackagingRow As DataGridViewRow In dgv_Packaging.SelectedRows
                Dim selectedPackaging As WireCertificatePackaging = CType(selectedPackagingRow.Tag, WireCertificatePackaging)
                _packagingSet.Remove(selectedPackaging)
            Next
            RefreshPackagingTable(_packagingSet.OrderBy(Function(x) x.Name))
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

#End Region


    Private Sub FillWireCertificateData()
        With _wireCertificate
            .CustomerAddressCity = _orderLine.Zlecenie.Klient.Miejscowosc
            .CustomerAddressCountry = _orderLine.Zlecenie.Klient.Kraj
            .CustomerAddressNumber = _orderLine.Zlecenie.Klient.Numer
            .CustomerAddressStreet = _orderLine.Zlecenie.Klient.Ulica
            .CustomerAddressZipCode = _orderLine.Zlecenie.Klient.KodPocztowy
            .CustomerEmail = _orderLine.Zlecenie.Klient.Email
            .CustomerName = _orderLine.Zlecenie.Klient.NazwaPelna
            .CustomerNip = _orderLine.Zlecenie.Klient.Nip
            .CustomerOrderNumber = txt_NumerZamowieniaKlienta.Text.Trim()
            .CustomerPhoneNumber = _orderLine.Zlecenie.Klient.Telefon
            .CustomerShortName = _orderLine.Zlecenie.Klient.NazwaSkrocona
            .Diameter = Decimal.Parse(txt_Wymiar.Text.Trim(), NumberStyles.Any)
            .GatunekLanguage = cmb_JezykGatunku.Text.ToLower().Trim()
            .GatunekName = cmb_Gatunek.Text
            .InvoiceNumber = txt_NumerFaktury.Text.Trim()
            .NormaWykonania = txt_NormaWykonania.Text.Trim()
            .OrderDate = dtp_DataZamowienia.Value
            .OrderNumber = _orderLine.Zlecenie.Numer.Trim()
            .PrintTime = dtp_DataWydruku.Value
            .ReportLanguage = cmb_WersjaJezykowa.SelectedItem.ToString()
            .SpoolCount = Integer.Parse(txt_IloscSztuk.Text.Trim())
            .ToleranceLower = Decimal.Parse(txt_TolDolna.Text.Trim(), NumberStyles.Any)
            .ToleranceUpper = Decimal.Parse(txt_TolGorna.Text.Trim(), NumberStyles.Any)
            .Weight = Decimal.Parse(txt_Waga.Text.Trim(), NumberStyles.Any)
            .WytopName = cmb_Wytop.Text.Trim()
            .Material = _material
            .OrderLine = _orderLine
            .Shipment = _shipment
        End With
    End Sub

    Private Sub ResetWireCertificateChemicalComposition()
        _wireCertificate.ChemicalComposition.Clear()

        Dim chemsList As IList(Of WireCertificateChemicalComposition)
        Try
            chemsList = _chemicalCompositionSet.OrderByDescending(Function(x) Decimal.Parse(x.ElementAmount)).ToList()
        Catch ex As Exception
            chemsList = _chemicalCompositionSet.OrderByDescending(Function(x) x.ElementName).ToList()
        End Try

        For Each chem As WireCertificateChemicalComposition In chemsList
            _wireCertificate.ChemicalComposition.Add(chem)
        Next
    End Sub

    Private Sub ResetWireCertificateMechanicalParameters()
        _wireCertificate.MechanicalParameters.Clear()
        For Each mechanicalParam As WireCertificateMechanicalParameters In _mechanicalParametersSet.OrderBy(Function(x) x.WireId)
            _wireCertificate.MechanicalParameters.Add(mechanicalParam)
        Next
    End Sub

    Private Sub ResetWireCertificatePackagingList()
        _wireCertificate.Packaging.Clear()
        For Each packaging As WireCertificatePackaging In _packagingSet.OrderBy(Function(x) x.Name)
            _wireCertificate.Packaging.Add(packaging)
        Next
    End Sub

    Private Sub AddWireCertificate()
        Dim wireCertificateRepository As New Repository(Of WireCertificate)(_unitOfWork)
        _unitOfWork.BeginTransaction()
        wireCertificateRepository.Add(_wireCertificate)
        _unitOfWork.CommitTransaction()
    End Sub

    Private Sub UpdateWireCertificate()
        Dim wireCertificateRepository As New Repository(Of WireCertificate)(_unitOfWork)
        _unitOfWork.BeginTransaction()
        wireCertificateRepository.Update(_wireCertificate)
        _unitOfWork.CommitTransaction()
    End Sub

    Private Sub btn_Accept_Click(sender As System.Object, e As System.EventArgs) Handles btn_Accept.Click
        Try
            If Not ValidateChildren() Then
                Throw New EntityDataInputException("Podane dane są nieprawidłowe." & vbNewLine &
                                                   "Popraw je i spróbuj ponownie.")
            End If

            'klient nie podal wytopu -> nie ma skladu chemicznego
            'If dgv_ChemicalComposition.Rows.Count = 0 Then
            '    Throw New EntityDataInputException("Proszę, uzupełnij skład chemiczny, aby kontynuować.")
            'End If

            If dgv_MechanicalParameters.Rows.Count = 0 Then
                Throw New EntityDataInputException("Proszę, uzupełnij parametry drutu, aby kontynuować.")
            End If

            If dgv_Packaging.Rows.Count = 0 Then
                Throw New EntityDataInputException("Proszę, podaj informację o opakowaniach, aby kontynuować.")
            End If

            Dim confirmationDialogResult As DialogResult = MessageBox.Show("Czy jesteś pewień?", "Uwaga!", MessageBoxButtons.YesNo, MessageBoxIcon.Warning)
            If confirmationDialogResult <> Windows.Forms.DialogResult.Yes Then
                Return
            End If

            Cursor = Cursors.WaitCursor


            FillWireCertificateData()
            ResetWireCertificateChemicalComposition()
            ResetWireCertificateMechanicalParameters()
            ResetWireCertificatePackagingList()

            If _wireCertificate.Id = 0 Then
                AddWireCertificate()
            Else
                UpdateWireCertificate()
            End If


            Dim wireCertificateReportService As New WireCertificateReportService()
            Dim wireCertificateReport As WireCertificateReport = wireCertificateReportService.GenerateReport(_wireCertificate)
            Dim printViewer As New frmPrintViewer(wireCertificateReport, False)
            printViewer.TopMost = True
            printViewer.WindowState = FormWindowState.Maximized
            printViewer.ShowDialog()

        Catch ex As EntityDataInputException
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning)
        Catch ex As Exception
            If _unitOfWork.IsTransactionActive() Then
                _unitOfWork.RollbackTransaction()
            End If
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        Finally
            Cursor = Cursors.Default
        End Try
    End Sub

    Private Sub btn_Cancel_Click(sender As System.Object, e As System.EventArgs) Handles btn_Cancel.Click
        If _previousForm IsNot Nothing Then
            _previousForm.Show()
        End If
    End Sub


End Class